package com.ds.iecs.im.store;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.validation.constraints.NotNull;

import org.mx.service.server.websocket.WsConnectKey;
import org.springframework.stereotype.Component;

/**
 * 存储连接WebSocket的IP、用户、系统等相关映射信息的类
 * 
 * @author john.peng
 *
 */
@Component("userMappingList")
public class UserMappingList {
	private Map<String, String> mapConnectKeyUser;
	private Map<String, Set<String>> mapUserConnectKey;
	private Map<String, String> mapUserSystem;
	private Map<String, Set<String>> mapSystemUser;

	/**
	 * 默认的构造函数
	 */
	public UserMappingList() {
		super();
		this.mapConnectKeyUser = new HashMap<String, String>();
		this.mapUserConnectKey = new HashMap<String, Set<String>>();
		this.mapUserSystem = new HashMap<String, String>();
		this.mapSystemUser = new HashMap<String, Set<String>>();
	}

	/**
	 * 根据用户ID获取相关的连接会话
	 * 
	 * @param userId 用户ID
	 * @return 连接会话关键字列表
	 */
	public Set<String> getConnectKeyByUser(String userId) {
		return this.mapUserConnectKey.get(userId);
	}

	/**
	 * 根据系统ID获取相关的连接会话
	 * 
	 * @param system 系统ID
	 * @return 连接会话关键字列表
	 */
	public Set<String> getConnectKeyBySystem(String system) {
		Set<String> users = this.mapSystemUser.get(system);
		Set<String> connectKeys = new HashSet<String>();
		for (String userId : users) {
			connectKeys.addAll(getConnectKeyByUser(userId));
		}
		return connectKeys;
	}

	/**
	 * 记入登入信息
	 * 
	 * @param connectKey 连接关键字
	 * @param userId     用户ID
	 * @param system     系统ID
	 */
	public void signedIn(@NotNull WsConnectKey connectKey, @NotNull String userId, @NotNull String system) {
		synchronized (mapConnectKeyUser) {
			String key = connectKey.toString();
			this.mapConnectKeyUser.put(key, userId);
			Set<String> set = this.mapUserConnectKey.get(userId);
			if (set == null) {
				set = new HashSet<String>();
			}
			set.add(key);
			this.mapUserConnectKey.put(userId, set);
		}
		synchronized (mapUserSystem) {
			this.mapUserSystem.put(userId, system);
			Set<String> set = this.mapSystemUser.get(system);
			if (set == null) {
				set = new HashSet<String>();
			}
			set.add(userId);
			this.mapSystemUser.put(system, set);
		}
	}

	/**
	 * 清除指定用户的登入信息
	 * 
	 * @param userId 用户ID
	 */
	public void signedOut(@NotNull String userId) {
		synchronized (mapConnectKeyUser) {
			// 清除指定用户关联的连接关键字
			Set<String> set = this.mapUserConnectKey.get(userId);
			if (set != null && !set.isEmpty()) {
				for (String key : set) {
					this.mapConnectKeyUser.remove(key);
				}
			}
			this.mapUserConnectKey.remove(userId);
		}
		synchronized (mapUserSystem) {
			// 清除指定用户关联的系统
			String system = this.mapUserSystem.get(userId);
			this.mapUserSystem.remove(userId);
			Set<String> set = this.mapSystemUser.get(system);
			if (set != null && set.contains(userId)) {
				set.remove(userId);
				this.mapSystemUser.put(system, set);
			}
		}
	}

	/**
	 * 踢出指定的用户登入信息
	 * 
	 * @param userIds 用户ID列表
	 */
	public void kickOut(String... userIds) {
		for (String userId : userIds) {
			signedOut(userId);
		}
	}
}
